﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Simulator
{
    [Serializable]
    public class Resource: Block
    {
        private int nBusy;
        /// <summary>
        /// Получить число занятых экземпляров ресурса
        /// </summary>
        public int NBusy {
            get { return nBusy; }
        }
        /// <summary>
        /// Узнать, есть ли свободные ресурсы?
        /// </summary>
        public bool AllBusy { get{return allBusy; }}
        private bool allBusy = false;
        /// <summary>
        /// Атомарные ресурсы
        /// </summary>
        public List<AtomicRes> Atoms{get; set;}
        private bool shared;
        /// <summary>
        /// Является ли ресурс разделяемым
        /// </summary>
        public bool Shared
        {
            get
            {
                return shared;
            }
            set
            {
                shared = value;
                busy.Clear();
            }
        }

        //Список занятости сущностями экземпляров данного ресурса
        private List<Entity> busy;

        private int mult = 1;
        /// <summary>
        /// Количество экземпляров данного ресурса
        /// </summary>
        public int Multiplicity {
            get{
                return mult;
            } 
            set
            {
                mult = value;
                if (!Shared)//если неразделяемый
                {
                    busy.Clear();
                    for (int i = 0; i < mult; i++)
                    {
                        busy.Add(null);//добавим, чтобы можно было обращаться busy[i]
                    }
                }
                else//если разделяемый, просто настроим 0
                    busy.Clear();
            }
        }

        /// <summary>
        /// Занять ресурс сущностью. Убедитесь, что ресурс не занят
        /// </summary>
        /// <param name="e">Сущность, которой будет занят этот ресурс</param>
        public override void PutEntity(ref Entity e)
        {
            //убедимся, что этой сущности нет
            if (busy.Contains(e))
                return;
            //если неразделяемый
            if (!Shared)
            {
                if (allBusy)
                {//если все экземпляры заняты
                    throw new Exception("Нельзя занять ресурс сущностью! Все экземпляры заняты!");
                }
                allBusy = true;
                int i = 0;
                for (; i < mult; i++)
                {//пройдем по всем экземплярам ресурса, найдем свободный
                    if (busy[i] == null)
                        break;
                }
                busy[i] = e;//займем i-й экземпляр, кот. свободен
                for (; i < mult; i++)
                {//пройдем дальше. Если свободные кончились, ставим флаг Busy
                    if (busy[i] == null)
                        allBusy = false;
                }
            }
            else
            {
                busy.Add(e);//просто добавим новую сущность
            }
            nBusy++;//в любом случае прибавим число занятых

        }
        /// <summary>
        /// Освободить ресурс от сущности
        /// </summary>
        /// <param name="e">Сущность</param>
        public void FreeEntity(Entity e)
        {
            if (!Shared)//если неразделяемый
            {
                //сначала найдем тот ресурс, который передан как параметр
                for (int i = 0; i < mult; i++)
                {
                    if (e == busy[i])
                    {
                        busy[i] = null;//освободим 
                        nBusy--;
                        allBusy = false;
                        break;
                    }
                }
            }
            else//раздяляемый ресурс
            {
                //если сущность содержится в блоке, освободим
                if (busy.Contains(e))
                {
                    nBusy--;
                    busy.Remove(e);//удалим сущность
                }
            }
            //если сущности е не было в блоке, то ничего не произойдет
        }
        public Resource()
        {
            Atoms = new List<AtomicRes>();
            busy = new List<Entity>();
            for (int i = 0; i < mult; i++)
            {
                busy.Add(null);
            }
            
            
        }

        /// <summary>
        /// Инициализирует ресурс с именем
        /// </summary>
        /// <param name="ID">Идентификатор (номер)</param>
        public Resource(string Name)
        {
            Atoms = new List<AtomicRes>();
            busy = new List<Entity>();
            for (int i = 0; i < mult; i++)
            {
                busy.Add(null);
            }
            this.Name = Name;
            
        }

        public override void ClearEntities()
        {//избавиться от всех сущностей, застрявших, мало ли, в блоке
            if (!Shared)//если неразделяемый
            {
                for (int i = 0; i < mult; i++)
                {
                    busy[i] = null;
                }
            }
            else
                busy.Clear();
            nBusy = 0;
            allBusy = false;
        }
    }
}
